package conf

import (
	"fmt"
	"go.uber.org/zap/zapcore"
	"os"

	"github.com/BurntSushi/toml"
	"github.com/natefinch/lumberjack"
	log "github.com/sirupsen/logrus"
	"go.uber.org/zap"
)

const (
	dev       = "dev"  //开发模式
	prod      = "prod" //线上模式
	SecretKey = "secret"
)

func Debug(args ...interface{}) {
	Logger.Debug(args...)
}

func Debugf(template string, args ...interface{}) {
	Logger.Debugf(template, args...)
}

func Info(args ...interface{}) {
	Logger.Info(args...)
}

func Infof(template string, args ...interface{}) {
	Logger.Infof(template, args...)
}

func Warn(args ...interface{}) {
	Logger.Warn(args...)
}

func Warnf(template string, args ...interface{}) {
	Logger.Warnf(template, args...)
}

func Error(args ...interface{}) {
	Logger.Error(args...)
}

func Errorf(template string, args ...interface{}) {
	Logger.Errorf(template, args...)
}

func Fatal(args ...interface{}) {
	Logger.Fatal(args...)
}

func Fatalf(template string, args ...interface{}) {
	Logger.Fatalf(template, args...)
}

func DPanic(args ...interface{}) {
	Logger.DPanic(args...)
}

func DPanicf(template string, args ...interface{}) {
	Logger.DPanicf(template, args...)
}

func Panic(args ...interface{}) {
	Logger.Panic(args...)
}

func Panicf(template string, args ...interface{}) {
	Logger.Panicf(template, args...)
}

// Logger 全局变量
var Logger *zap.SugaredLogger

// 日志级别
var levelMap = map[string]zapcore.Level{
	"debug":  zapcore.DebugLevel,
	"info":   zapcore.InfoLevel,
	"warn":   zapcore.WarnLevel,
	"error":  zapcore.ErrorLevel,
	"fatal":  zapcore.FatalLevel,
	"dpanic": zapcore.DPanicLevel,
	"panic":  zapcore.PanicLevel,
}

func getLoggerLevel(logLevel string) zapcore.Level {
	if level, ok := levelMap[logLevel]; ok {
		return level
	}
	return zapcore.InfoLevel
}

type appcfg struct {
	Title        string `toml:"title"`          //
	Intro        string `toml:"intro"`          //
	Mode         string `toml:"mode"`           //
	Addr         string `toml:"addr"`           //
	Srv          string `toml:"srv"`            //
	TokenKey     string `toml:"token_key"`      //token关键词
	TokenExp     int    `toml:"token_exp"`      //过期时间 h
	TokenKeep    bool   `toml:"token_keep"`     //保持在线
	TokenSso     bool   `toml:"token_sso"`      //单点登录
	TokenSecret  string `toml:"token_secret"`   //加密私钥
	ImageCut     bool   `toml:"image_cut"`      //图片裁剪
	ImageWidth   int    `toml:"image_width"`    //图片宽度
	ImageHeight  int    `toml:"image_height"`   //图片高度
	PageMin      int    `toml:"page_min"`       //最小分页大小
	PageMax      int    `toml:"page_max"`       //最大分页大小
	DbHost       string `toml:"db_host"`        //数据库地址
	DbPort       int    `toml:"db_port"`        //数据库端口
	DbUser       string `toml:"db_user"`        //数据库账号
	DbPasswd     string `toml:"db_passwd"`      //数据库密码
	DbName       string `toml:"db_name"`        //数据库名称
	DbParams     string `toml:"db_params"`      //数据库参数
	OrmIdle      int    `toml:"orm_idle"`       //
	OrmOpen      int    `toml:"orm_open"`       //
	OrmShow      bool   `toml:"orm_show"`       //显示sql
	OrmSync      bool   `toml:"orm_sync"`       //同步表结构
	OrmCacheUse  bool   `toml:"orm_cache_use"`  //是否使用缓存
	OrmCacheSize int    `toml:"orm_cache_size"` //缓存数量
	OrmHijackLog bool   `toml:"orm_hijack_log"` //劫持日志
	Author       struct {
		Name    string `toml:"name"`
		Website string `toml:"website"`
	} `toml:"author"`
	Wechat struct {
		GzhAppid  string `toml:"gzh_appid"`  //公众号
		GzhSecret string `toml:"gzh_secret"` //公众号
		MpgAppid  string `toml:"mpg_appid"`  //小程序
		MpgSecret string `toml:"mpg_secret"` //小程序
		WebAppid  string `toml:"web_appid"`  //web
	} `toml:"wechat"`
	Qq struct {
		WebAppid  string `toml:"web_appid"`  //web
		WebSecret string `toml:"web_secret"` //appkey-申请名称appkey,对接名称secret
	} `toml:"qq"`
}

func (app *appcfg) IsProd() bool {
	return app.Mode == prod
}
func (app *appcfg) IsDev() bool {
	return app.Mode == dev
}

// mb4 most bytes 4
// uid:pass@tcp(host:port)/dbname?charset=utf8mb4&parseTime=true&loc=Local
// 用户名:密码@tcp(主机:端口)/数据库名称?charset=utf8mb4&parseTime=true&loc=Local
const _dsn = "%s:%s@tcp(%s:%d)/%s?%s"

// Dsn MySQL链接字符串
func (app *appcfg) Dsn() string {
	return fmt.Sprintf(_dsn, app.DbUser, app.DbPasswd, app.DbHost, app.DbPort, app.DbName, app.DbParams)
}

var (
	App       *appcfg              //运行配置实体
	defConfig = "./conf/conf.toml" //配置文件路径，方便测试
)

func Init() {
	var err error
	App, err = initCfg()
	if err != nil {
		log.Fatal("config init error : ", err.Error())
	}
	log.Debug("conf init")

	// 日志文件
	logPath := "./debug.log"
	// 这里通过读取配置文件来获取
	logLevel := "debug"
	level := getLoggerLevel(logLevel)
	hook := lumberjack.Logger{
		Filename:   logPath,
		MaxSize:    128,
		MaxBackups: 14,
		MaxAge:     14,
		LocalTime:  true,
		Compress:   true,
	}
	syncWriter := zapcore.AddSync(&hook)
	encoderConfig := zap.NewProductionEncoderConfig()
	// 时间格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.LowercaseColorLevelEncoder

	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(encoderConfig),
		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), syncWriter),
		zap.NewAtomicLevelAt(level),
	)
	Logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)).Sugar()

}

func initCfg() (*appcfg, error) {
	app := &appcfg{}
	_, err := toml.DecodeFile(defConfig, &app)
	if err != nil {
		return nil, err
	}
	return app, nil
}
